//
//
//
//
//
//
// StrStream.C
//

#include "StrStream.h"

namespace Util
{
	StrStream::StrStream() : _size(1), _capability(128)
	{
		_buf = new char[_capability];
		memset(_buf, 0, _capability);
	}
	
	StrStream::StrStream(const char* msg)
	{
		U32 len = strlen(msg) + 1;
		if(len <= 128)
		{
			_capability = 128;
			_buf = new char[_capability];
			strcpy(_buf, msg);

			_size = len;
		}
		else
		{
			U32 h = len >> 3;
			U32 l = len % 8;

			U32 n = l ? (h + 1) * 8 : h * 8;
			_capability = n;

			_buf = new char[_capability];
			strcpy(_buf, msg);
			_size = strlen(msg) + 1;
		}
	}

	StrStream::StrStream(U32 size)
	{
		U32 h = size >> 3;
		U32 l = size % 8;

		U32 n = l ? (h + 1) * 8 : h * 8;
		_capability = n;
		_size = 1;
		_buf = new char[_capability];
		memset(_buf, 0, _capability);
	}

	StrStream::~StrStream(){delete _buf;}

	StrStream& StrStream::operator<< (U8 msg)
	{
		NeedEnlg(1);
		sprintf(_buf + _size - 1, "%c", msg);
		_size += 1;
		return *this;
	}

	StrStream& StrStream::operator<< (U16 msg)
	{
		NeedEnlg(2);
		sprintf(_buf + _size - 1, "%d", msg);
		_size += 2;
		return *this;
	}

	StrStream& StrStream::operator<< (U32 msg)
	{
		NeedEnlg(4);
		sprintf(_buf + _size - 1, "%u", msg);
		_size += 4;
		return *this;
	}

	StrStream& StrStream::operator<< (S32 msg)
	{
		NeedEnlg(4);
		sprintf(_buf + _size - 1, "%d", msg);
		_size += 4;
		return *this;
	}
	StrStream& StrStream::operator<< (const std::string& msg)
	{
		NeedEnlg(msg.length());
		memcpy(_buf + _size - 1, msg.c_str(), msg.length() + 1);
		_size += msg.length();
		return *this;
	}

	StrStream& StrStream::operator<< (const char* msg)
	{
		U32 l = strlen(msg);
		NeedEnlg(l);

		memcpy(_buf + _size - 1, msg, l + 1);
		_size += l;
		return *this;
	}

	void StrStream::NeedEnlg(U32 num)
	{
		if(_capability - _size >= num)
			return;
		
		U32 h = num >> 3;
		U32 l = num % 8;

		U32 n = l ? (h + 1) * 8 : h * 8;
		_capability += n;

		char* p = new char[_capability];
		memcpy(p, _buf, _size);
		delete _buf;
		_buf = p;
	}

	const char* StrStream::Str() const
	{
		return _buf;
	}

	StrStream::operator std::string() const
	{
		return std::string(_buf);
	}

	StrStream::operator const char* () const
	{
		return _buf;
	}

	std::string StrStream::AsString(void) const
	{
		return std::string(_buf);
	}
};
